#include <surface\bezierSurface.h>
#include <surface\bernsteinPolynom.h>

#include <iostream>
#include <iomanip>

void 
bezierSurface::addControlPoint(int x, int y, vec3f point) {
  control_points[y][x] = point;
}

vec3f
bezierSurface::getControlPoint(int x, int y) {
  return control_points[y][x];
}

vec3f **
bezierSurface::getBezierPoints() {
  return bezier_points;
}

void 
bezierSurface::clearSurfaceNoDelete() {

  for (int y = 0; y != 4; y++) {
    for (int x = 0; x != 4; x++) {
      control_points[y][x] = vec3f(0.0, 0.0, 0.0);
    }
  }

  if (bezier_points) {
    delete [] bezier_points;
    bezier_points = NULL;
  }
}

void
bezierSurface::computeSurface(int resolution) {

  int i, j;
  int u, v;
  vec3f p;

  if (!bezier_points) {
    surface_resolution = resolution;
    bezier_points = (vec3f **) new vec3f *[resolution];
    for (int row = 0; row != surface_resolution; row++) {
      bezier_points[row] = (vec3f *) new vec3f[resolution];
    }
  }

  for (v = 0; v < resolution; v += 1) {
    for (u = 0; u < resolution; u += 1) {
      
      p[0] = control_points[0][0][0] - v;
      p[1] = control_points[0][0][1] - u;
      p[2] = 0.0;

      // compute points on the bezier surface
      for (j = 0; j < 4; j++) {
        for (i = 0; i < 4; i++) {
          p[2] += control_points[j][i][2] * bernsteinPolynom::compute(i, (float) u / (float) resolution)
                                          * bernsteinPolynom::compute(j, (float) v / (float) resolution);
        }
      }

      bezier_points[v][u] = p;
      //std::cout << setiosflags (ios::fixed) << "x:" << p[0] << "y:" << p[1] << "z:" << p[2] << std::endl;
    }
  }

}

bezierSurface::bezierSurface() {
   bezier_points = NULL;
}
